import random

import torch
import d2l

true_w = torch.tensor([2, -3.4])
true_b = 4.2

features, labels = d2l.synthetic_data(true_w, true_b, 1000)

# print(f'features: {features}')
# print(f'features[0]: {features[0]}')
# print(f'features[:, 1]: {features[:, 1]}')
# print(f'features[:, :]: {features[:, :]}')
# print(f'features[:, 0:2]: {features[:, 0:2]}')
# print(f'labels[0]: {labels[0]}')

# d2l.set_figsize()
# d2l.plt.scatter(features[:, (1)].detach().numpy(), labels.detach().numpy(), 1)
#
# d2l.plt.show()

def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indicies = torch.tensor(indices[i: min(i + batch_size, num_examples)])
        yield features[batch_indicies], labels[batch_indicies]


batch_size = 10

w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

lr = 0.03
num_epoches = 3
net = d2l.linreg
loss = d2l.squared_loss

for epoch in range(num_epoches):
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y)
        l.sum().backward()
        d2l.sgd([w, b], lr, batch_size)
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')
